package packeter

import (
	"fmt"

	"github.com/project-flogo/core/data/metadata"

	"github.com/project-flogo/core/activity"
	"github.com/project-flogo/core/engine/channels"
)

type Activity struct {
	settings Settings
	data     []EdgeChannelData
	channel  channels.Channel
}

func init() {
	_ = activity.Register(&Activity{}, New) //activity.Register(&Activity{}, New) to create instances using factory method 'New'
}

// type settings struct{}

func New(ctx activity.InitContext) (activity.Activity, error) {
	settings := Settings{}
	err := metadata.MapToStruct(ctx.Settings(), &settings, true)
	if err != nil {
		return nil, err
	}
	channel, err := channels.New(settings.OutputChannel, 10)
	if err != nil {
		return nil, err
	}
	act := &Activity{
		settings: settings,
		channel:  channel,
	}
	return act, nil
}

var activityMd = activity.ToMetadata(&Settings{}, &Input{}, &Output{})

func (a *Activity) Metadata() *activity.Metadata {
	return activityMd
}

func (a *Activity) Eval(ctx activity.Context) (bool, error) {
	input := &Input{}
	err := ctx.GetInputObject(input)
	if err != nil {
		ctx.Logger().Errorf("failed parse input: %s", err.Error())
		return true, err
	}
	switch input.Action {
	case "INPUT":
		{
			a.data = append(a.data, input.Datum)
			count := len(a.data)
			if a.settings.MaxOutputCount > 0 && count > a.settings.MaxOutputCount {
				a.channel.Publish(a.data[:a.settings.MaxOutputCount])
				a.data = a.data[a.settings.MaxOutputCount:]
			}
			err = nil
			break
		}
	case "OUTPUT":
		{
			count := len(a.data)
			if count > a.settings.MinOutputCount {
				a.channel.Publish(a.data)
				a.data = []EdgeChannelData{}
			}
			err = nil
			break
		}
	default:
		{
			err = fmt.Errorf("unknown action: %s", input.Action)
		}
	}

	errStr := ""
	if err != nil {
		errStr = err.Error()
	}
	output := &Output{
		Count: len(a.data),
		Err:   errStr,
	}

	err = ctx.SetOutputObject(output)
	return true, err
}
